﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using BlogApi.Models;
using BlogApi.ModelsDto;
using BlogApi.Services;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace BlogApi.Controllers
{
    [Route("api/article")]
    [ApiController]
    public class ArticleController : ControllerBase
    {
        private readonly IArticleRepository _articleRepository;
        private readonly ILikeRepository _likeRepository;
        private readonly IMapper _mapper;
        private readonly IArticleToArticleTagRepository _articleToArticleTagRepository;

        public ArticleController(ILikeRepository likeRepository,IArticleRepository articleRepository,IArticleToArticleTagRepository articleToArticleTagRepository,IMapper mapper)
        {
            _articleRepository = articleRepository ?? throw new ArgumentNullException(nameof(articleRepository));
            _likeRepository = likeRepository ?? throw new ArgumentNullException(nameof(likeRepository));
            _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
            _articleToArticleTagRepository = articleToArticleTagRepository ?? throw new ArgumentNullException(nameof(articleToArticleTagRepository));
        }
        [HttpPost]
        [Route("saveArticle")]
        public async Task<IActionResult> AddArticle([FromBody]ArticleAddDto articleAddDto)
        {
            var articleEntity = _mapper.Map<Article>(articleAddDto);
            _articleRepository.AddArticle(articleEntity);
            foreach(var item in articleAddDto.ArticleTagList)
            {
                var articleToArticleTagEntity = new ArticleToArticleTag()
                {
                    ArticleId = articleEntity.Id,
                    ArticleTagId = item
                };
                _articleToArticleTagRepository.AddArticleToArticleTag(articleToArticleTagEntity);
            }
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "ok"
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpGet]
        [Route("articleList/{index}")]
        public async Task<IActionResult> GetArticleListAndUserInfoByPage([FromRoute]int index)
        {
            var articleListAndUserInfo = await _articleRepository.GetArticleAndUserInfosByPageAsync(7, index);
            return new JsonResult(new
            {
                articleList = articleListAndUserInfo
            });
        }
        [HttpGet]
        [Route("hotArticleList")]
        public async Task<IActionResult> GetHotArticleList()
        {
            var hotArticles = await _articleRepository.GetArticleAndUserInfosByPageOrderByBrowseNumber(7, 0);
            return new JsonResult(new
            {
                hotArticleList = hotArticles
            });
        }
        [HttpGet]
        [Route("articleDetail/{articleId}")]
        public async Task<IActionResult> GetArticleDetail([FromRoute]Guid articleId)
        {
            var article = await _articleRepository.GetArticleAsync(articleId);
            var articleTagIds = await _articleToArticleTagRepository.GetArticleToArticleTagsByArticleIdAsync(articleId);
            List<Guid> tagIds = new List<Guid>();
            foreach(var item in articleTagIds)
            {
                tagIds.Add(item.ArticleTagId);
            }
            return new JsonResult(new
            {
                articleDetail = new
                {
                    articleId = article.Id,
                    authorId = article.UserId,
                    articleTitle = article.Title,
                    articleTagIdList = tagIds,
                    goodCount = article.GoodNumber,
                    browseCount = article.BrowseNumber,
                    commentCount = article.CommentNumber,
                    createdDate = article.PublishedDate.ToString("yyyy-MM-dd"),
                    articleMarkDownContent = article.Content
                }
            });
        }
        [HttpPost]
        [Route("good")]
        public async Task<IActionResult> LikeArticle([FromBody]LikeAddDto likeAddDto)
        {
            var currentArticle = await _articleRepository.GetArticleAsync(likeAddDto.ArticleId);
            var likeEntity = _mapper.Map<Like>(likeAddDto);
            _likeRepository.AddLike(likeEntity);
            currentArticle.GoodNumber++;
            _articleRepository.UpdateArticle(currentArticle);
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "success",
                    goodCount = currentArticle.GoodNumber
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("cancelGood")]
        public async Task<IActionResult> CancelLikeArticle([FromBody]LikeDeleteDto likeDeleteDto)
        {
            var likeEntity = await _likeRepository.GetLikeAsync(likeDeleteDto.ArticleId, likeDeleteDto.UserId);
            var currentArticle = await _articleRepository.GetArticleAsync(likeDeleteDto.ArticleId);
            _likeRepository.DeleteLike(likeEntity);
            currentArticle.GoodNumber--;
            _articleRepository.UpdateArticle(currentArticle);
            if(await _likeRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "success",
                    goodCount = currentArticle.GoodNumber
                });
            }
            else
            {
                return BadRequest();
            }
            
        }
        [HttpGet]
        [Route("articleListByTag/{tagId}/{index}")]
        public async Task<IActionResult> GetArticleListByTag([FromRoute]Guid tagId, [FromRoute]int index)
        {
            var articleToArticleTagList = await _articleToArticleTagRepository.GetArticleToArticleTagsByTagIdAsync(tagId, 7, index);
            List<ArticleAndUserInfoDto> articleListByTag = new List<ArticleAndUserInfoDto>();
            foreach(var item in articleToArticleTagList)
            {
                articleListByTag.Add(await _articleRepository.GetArticleAndUserInfoDtoByArticleIdAsync(item.ArticleId));
            }
            return new JsonResult(new
            {
                articleList = articleListByTag
            });
        }
        [HttpGet]
        [Route("myArticleList/{userId}/{index}")]
        public async Task<IActionResult> GetMyArticleList([FromRoute]Guid userId, [FromRoute]int index)
        {
            var myArticleList = await _articleRepository.GetUserArticlesByPageAsync(userId, 10, index);
            var myArticleListDto = _mapper.Map<IEnumerable<ArticleDto>>(myArticleList);
            return new JsonResult(new
            {
                myArticleListData = myArticleListDto
            });
        }
        [HttpPost]
        [Route("deleteMyArticle")]
        public async Task<IActionResult> DeleteArticle([FromBody]ArticleDeleteDto articleDeleteDto)
        {
            var articleEntity = await _articleRepository.GetArticleAsync(articleDeleteDto.ArticleId);
            _articleRepository.DeleteArticle(articleEntity);
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "ok"
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("publishArticle")]
        public async Task<IActionResult> PublishArticle([FromBody]ArticlePublishDto articlePublishDto)
        {
            var articleEntity = await _articleRepository.GetArticleAsync(articlePublishDto.ArticleId);
            if (articleEntity == null)
            {
                return BadRequest();
            }
            articleEntity.Status = "published";
            articleEntity.PublishedDate = DateTime.Now;
            _articleRepository.UpdateArticle(articleEntity);
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "ok"
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("cancelPublished")]
        public async Task<IActionResult> CancelPublishArticle([FromBody]ArticlePublishDto articlePublishDto)
        {
            var articleEntity = await _articleRepository.GetArticleAsync(articlePublishDto.ArticleId);
            if (articleEntity == null)
            {
                return BadRequest();
            }
            articleEntity.Status = "notPublished";
            _articleRepository.UpdateArticle(articleEntity);
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "ok"
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("updateMyArticle")]
        public async Task<IActionResult> UpdateArticle(ArticleUpdateDto articleUpdateDto)
        {
            var articleEntity = await _articleRepository.GetArticleAsync(articleUpdateDto.ArticleId);
            if (articleEntity == null)
            {
                return BadRequest();
            }
            articleEntity.Title = articleUpdateDto.ArticleTitle;
            articleEntity.Content = articleUpdateDto.ArticleMarkDown;
            _articleRepository.UpdateArticle(articleEntity);
            var articleToArticleTagList = await _articleToArticleTagRepository.GetArticleToArticleTagsByArticleIdAsync(articleUpdateDto.ArticleId);
            //删除原来关系表中文章与TAG的关系
            foreach(var item in articleToArticleTagList)
            {
                _articleToArticleTagRepository.DeleteArticleToArticleTag(item);
            }
            //把新数据加入
            foreach(var item in articleUpdateDto.ArticleTagList)
            {
                var articleToArticleTagEntity = new ArticleToArticleTag()
                {
                    ArticleId = articleEntity.Id,
                    ArticleTagId = item
                };
                _articleToArticleTagRepository.AddArticleToArticleTag(articleToArticleTagEntity);
            }
            //保存更改到数据库
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "ok"
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpPost]
        [Route("addBrowseNumber")]
        public async Task<IActionResult> AddArticleBrowseNumber([FromBody]ArticleBrowseAddDto articleBrowseAddDto)
        {
            var articleEntity = await _articleRepository.GetArticleAsync(articleBrowseAddDto.ArticleId);
            articleEntity.BrowseNumber++;
            _articleRepository.UpdateArticle(articleEntity);
            if(await _articleRepository.SaveAsync())
            {
                return new JsonResult(new
                {
                    status = "ok"
                });
            }
            else
            {
                return BadRequest();
            }
        }
        [HttpGet]
        [Route("spaceArticleList/{userId}/{index}")]
        public async Task<IActionResult> GetSpaceArticleList([FromRoute]Guid userId,[FromRoute]int index)
        {
            var spaceArticleList = await _articleRepository.GetUserSpaceArticleByPageAsync(userId, 10, index);
            var spaceArticleData = _mapper.Map<IEnumerable<ArticleDto>>(spaceArticleList);
            return new JsonResult(new
            {
                spaceArticleListData = spaceArticleData
            });
        }
        [HttpGet]
        [Route("searchPublishedArticle")]
        public async Task<IActionResult> SearchPublishedArticle([FromQuery]string keyword,[FromQuery]int index)
        {
            var data = await _articleRepository.SearchPublishedArticleByPage(keyword, 7, index);
            return new JsonResult(new
            {
                articleList = data
            });
        }
    }
}